
from sqlalchemy import Column, String, Integer
from sqlalchemy.orm import Session

from FastApi import ErrorCode
from FastApi.Database import Base
from FastApi.UtilsWeb import Error
from Lib.Utils import Password, GeneratorToken


class UserTokenSchema(Base):
    __tablename__ = "game_token"
    id = Column(Integer, primary_key=True, index=True)
    user_id = Column(Integer)
    create_time = Column(Integer)
    expire_time = Column(Integer)
    token = Column(String(36))
    device = Column(String(10))

    def GenerateToken(self, user_id: int, device: str, db: Session):
        res_token = db.query(UserTokenSchema).filter(
                UserTokenSchema.user_id == user_id and device == UserTokenSchema.device).first()
        import time
        now_time = int(time.time())
        if res_token:
            expire_time = res_token.expire_time
            if now_time >= expire_time:
                db.query(UserTokenSchema).filter(
                        UserTokenSchema.user_id == user_id and device == UserTokenSchema.device).update({
                        "token"      : GeneratorToken(),
                        "expire_time": self.GenerateExpireTime()
                })
                db.commit()
            return res_token.token
        else:
            token = GeneratorToken()
            token_data = UserTokenSchema(
                    user_id=user_id,
                    create_time=now_time,
                    expire_time=self.GenerateExpireTime(),
                    token=token,
                    device=device
            )
            db.add(token_data)
            db.commit()
            db.refresh(token_data)
            return token

    def GenerateExpireTime(self, expire_time=60 * 60 * 12):
        import time
        return int(time.time() + expire_time)

    def GetUserInfo(self, token: str, device: str, db: Session):
        user_id = db.query(UserTokenSchema).filter(
                UserTokenSchema.token == token and UserTokenSchema.device == device).first()['user_id']
        return UserModel().GetUserByUserId(user_id)


class UserModel(Base):
    error: Error

    __tablename__ = "game_user"
    id = Column(Integer, primary_key=True, index=True)
    user_name = Column(String(255))
    user_pass = Column(String(255))
    user_nickname = Column(String(255))
    open_id = Column(String(255))
    avatar = Column(String(255))
    gold = Column(Integer)
    carbonic = Column(Integer)
    alloy = Column(Integer)
    ticket = Column(Integer)

    def Add(self, db: Session, user_name: str, user_pass: str):
        if self.GetUserByUserName(db, user_name):
            self.error = Error(ErrorCode.UNIQUE_USER_NAME, "用户名重复")
            return False
        data = UserModel(
                user_name=user_name,
                user_pass=user_pass,
                user_nickname=user_name,
                open_id="",
                avatar="",
                gold=0,
                carbonic=0,
                alloy=0,
                ticket=0,
        )
        db.add(data)
        db.commit()
        db.refresh(data)
        return self.GetUserByUserName(db, data.user_name)

    def GetUserByUserName(self, db: Session, user_name: str):
        return db.query(UserModel).filter(UserModel.user_name == user_name).first()

    def LoginByUserNameAndPwd(self, db: Session, user_name: str, password: str):
        data = db.query(UserModel) \
            .filter(UserModel.user_name == user_name, UserModel.user_pass == Password(password)).first()
        if not data: return None
        return {**{
                "user_id"      : data.id,
                "user_name"    : data.user_name,
                "user_pass"    : data.user_pass,
                "user_nickname": data.user_nickname
        }, **self.GetUserToken(data.id, "app", db)}

    def GetUserToken(self, user_id: int, device: str, db: Session):
        return {"token": UserTokenSchema().GenerateToken(user_id, device, db)}

    def GetUserByUserId(self, user_id, db: Session):
        return db.query(UserModel).filter(UserModel.id == user_id).first()
